package com.emser.unc.client.presenter;

import java.util.ArrayList;

import com.emser.unc.client.CloudMobile;
import com.emser.unc.client.event.AddSellerEvent;
import com.emser.unc.client.event.EditCustomerListEvent;
import com.emser.unc.client.event.EditProductListEvent;
import com.emser.unc.client.event.EditSellerEvent;
import com.emser.unc.client.helper.RPCCall;
import com.emser.unc.client.service.SellerService;
import com.emser.unc.client.service.SellerServiceAsync;
import com.emser.unc.serializable.ResultDTO;
import com.emser.unc.serializable.SellerDTO;
import com.emser.unc.serializable.UserAccountDTO;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.HasScrollHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

public class SellerPresenter implements Presenter{	
	private final Display display;
	private SimpleEventBus eventBus; 
	private SellerServiceAsync rpcSellerService;
	private UserAccountDTO userA;
	private boolean search, scrollEnable;
	private ArrayList<String> searchParam;
	private static final int pageSize = 15;
	private int rangeStart, rangeLength, size, lastScrollPos;
	private SellerDTO sellerDTO = null;
	private String pageCursor = null;
	private SellerPresenter sellerPresenter;
	
	public interface Display {	
	    Widget asWidget();
	    HasClickHandlers getSearchButton();
	    HasClickHandlers getAddButton();
	    HasClickHandlers getRemoveButton();
	    HasClickHandlers getBtnCustomers();
	    HasClickHandlers getBtnProducts();
	    HasClickHandlers getBtnPopUpDCancel();
	    HasClickHandlers getBtnPopUpDDelete();
	    HasData<SellerDTO> getCellList();
	    HasText getName();
	    HasText getLastName();
	    HasText getAddress();
	    HasText getTelephone();
	    HasText getUserName();
	    HasText getPassword();
	    HasText getSerialDevice();
	    HasText getZP();
	    HasText getCity();
	    SingleSelectionModel<SellerDTO> getSelectionM();
	    HasScrollHandlers getScrollPanel();
	    HasClickHandlers getEditButton();
		HasValue<String> getSearchParam();
		HasKeyPressHandlers getSearchTexBox();
		void setRange(int start, int lenght,int size);
		void showWarning();
		void disableWarning();
		void enableDelete(boolean enabled);
		void enableBtnAdd(boolean enabled);
		void enableBtnEdit(boolean enabled);
		void enableBtnPopUpDelete(boolean enabled);
		void enableBtnSearch(boolean enabled);		
		void showBusyIndicator();
		void hideBusyIndicator();		
		void enableBtnCustomers(boolean enabled);
		void enableBtnProducts(boolean enabled);
		int getVerticalScrollPosition();
		int getMaximumVerticalScrollPosition();
	}
	
	public SellerPresenter( UserAccountDTO user,SimpleEventBus eventBus, Display display) {
		this.rpcSellerService = GWT.create(SellerService.class);	
		this.eventBus = eventBus;
		this.userA = user;
		rangeStart = 0;
		rangeLength = pageSize;
		this.display = display;
		this.display.enableBtnCustomers(false);
		this.display.enableBtnEdit(false);
		this.display.enableDelete(false);
		this.display.enableBtnProducts(false);
		sellerPresenter = this;
		bind();	
	}
	
		
	private void bind() {
		this.display.getSearchTexBox().addKeyPressHandler(new KeyPressHandler() {
		      public void onKeyPress(KeyPressEvent event) {
		          if (event.getCharCode() == KeyCodes.KEY_ENTER) {
		        		display.enableBtnSearch(false);
						handleSearchEvent();
						display.enableBtnSearch(true);
		          }
		        }
		 	   });

		
		this.display.getSearchButton().addClickHandler(new ClickHandler() {   
			public void onClick(ClickEvent event) {
				display.enableBtnSearch(false);
				handleSearchEvent();
				display.enableBtnSearch(true);
				
		      }
		});
		this.display.getAddButton().addClickHandler(new ClickHandler() {   
		      public void onClick(ClickEvent event) {
		    	  display.enableBtnAdd(false);
		    	  eventBus.fireEvent(new AddSellerEvent(rpcSellerService));
		    	  display.enableBtnAdd(true);
		      }
		});
		this.display.getRemoveButton().addClickHandler(new ClickHandler() {   
		      public void onClick(ClickEvent event) {
		    	  if(display.getSelectionM().getSelectedObject()!= null){
		    		  display.enableDelete(false);
		    		  display.showWarning();	  
		    	  }		    	  
		      }
		});
		this.display.getEditButton().addClickHandler(new ClickHandler() {   
			public void onClick(ClickEvent event) {
				if(display.getSelectionM().getSelectedObject()!= null)
					eventBus.fireEvent(new EditSellerEvent(display.getSelectionM().getSelectedObject(),rpcSellerService));
		      }
		});
		this.display.getScrollPanel().addScrollHandler(new ScrollHandler() {
	        public void onScroll(ScrollEvent event) {
	        	if(scrollEnable)
	        		doScroll();
	        }
	    });
		this.display.getSelectionM().addSelectionChangeHandler(new SelectionChangeEvent.Handler() {  
			public void onSelectionChange(SelectionChangeEvent event) {
		    	display.enableBtnCustomers(true);
		  		display.enableBtnEdit(true);
		  		display.enableDelete(true);
		  		display.enableBtnProducts(true);
		    	setInfo(display.getSelectionM().getSelectedObject());
		    }
		});  
		this.display.getBtnCustomers().addClickHandler(new ClickHandler() {   
			public void onClick(ClickEvent event) {
				if(display.getSelectionM().getSelectedObject() != null){
					sellerDTO = display.getSelectionM().getSelectedObject();
					eventBus.fireEvent(new EditCustomerListEvent(sellerPresenter));
				}
				}
		});
		this.display.getBtnProducts().addClickHandler(new ClickHandler() {   
			public void onClick(ClickEvent event) {
				if(display.getSelectionM().getSelectedObject() != null){
					sellerDTO = display.getSelectionM().getSelectedObject();
					eventBus.fireEvent(new EditProductListEvent(sellerPresenter));
				} 	
			}
		});
		this.display.getBtnPopUpDDelete().addClickHandler(new ClickHandler() {   
		      public void onClick(ClickEvent event) {
		    	  display.enableBtnPopUpDelete(false);
		    	  display.disableWarning();
		    	  doRemove();  	
		    	  display.enableBtnPopUpDelete(true);
		      }
		});
		this.display.getBtnPopUpDCancel().addClickHandler(new ClickHandler() {   
		      public void onClick(ClickEvent event) {
		    	  display.disableWarning();
		    	  display.enableDelete(true);
		      }
		});
	}

	private void handleSearchEvent(){
		String line,word,subword;
		String [] elements, subElements;
		line = display.getSearchParam().getValue();
		if(!line.isEmpty()){
			searchParam = new ArrayList<String>();
			searchParam.add(userA.getName());
			elements = line.split("\\s+");
			for(int j=0;j<elements.length;j++){
				word = elements[j];
				subElements = word.split(",");
				for(int i = 0;i<subElements.length;i++){
					subword = subElements[i];
					searchParam.add(subword);
				}
			}
			if(searchParam.size()< 5){
				search = true;
				pageCursor = null;
				rangeStart = 0;
				rangeLength = pageSize;
				clearInfo();
				updateSRowQuantity();
			}
		}
	}
	
	private void doSearch(int startS, int lengthS) {
			final int start = startS;
			final int length = lengthS;
			display.showBusyIndicator();
			new RPCCall<ResultDTO<SellerDTO>>(){
				@Override
				public void onFailure(Throwable caught) {
					display.hideBusyIndicator();
					Window.alert(CloudMobile.constants.eSearchSellers());
				}
				@Override
				public void onSuccess(ResultDTO<SellerDTO> result) {
					display.hideBusyIndicator();
					display.setRange((start+1), length, size);
					if(result != null){
						pageCursor = result.getCursorString();
						display.getCellList().setRowData(start, result.getList());;
					}
					scrollEnable = true;
				}
				@Override
				protected void callService(AsyncCallback<ResultDTO<SellerDTO>> cb) {
					rpcSellerService.getSearchSellers(pageCursor,pageSize, searchParam,cb);	
				}
			}.retry(3);
	}

	private void doRemove() {
		final SellerDTO  sellerTemp = display.getSelectionM().getSelectedObject();
		final String  sellerName = display.getSelectionM().getSelectedObject().getUserName();
		search = false;
		if(sellerName != null){
			new RPCCall<Boolean>(){
				@Override
				public void onFailure(Throwable caught) {
					display.hideBusyIndicator();
					Window.alert(CloudMobile.constants.eDelete());
					display.enableDelete(true);
				}
				@Override
				public void onSuccess(Boolean result) {
					display.hideBusyIndicator();
					if(result){
						clearInfo();
						pageCursor = null;
						rangeStart = 0; 
						updateRowQuantity();
						display.getSelectionM().setSelected(sellerTemp, false);
						display.enableDelete(true);
						
					}else{
						Window.alert(CloudMobile.constants.eServerDelete());
						display.enableDelete(true);
					}					
				}
				@Override
				protected void callService(AsyncCallback<Boolean> cb) {
					rpcSellerService.deleteSeller(userA.getName(),sellerName,cb);					
				}
			}.retry(3);
		}
	}
	
	private void setInfo(SellerDTO seller){
		this.display.getName().setText(seller.getFirstName());
		this.display.getLastName().setText(seller.getLastName());
		this.display.getPassword().setText(seller.getUserPassword());
		this.display.getAddress().setText(seller.getAddress());
		this.display.getCity().setText(seller.getCity());
		this.display.getTelephone().setText(seller.getTelephone());
		this.display.getUserName().setText(seller.getUserName());
		this.display.getZP().setText(seller.getZipCode());
		if(seller.getSerialDevice()!= null)
			this.display.getSerialDevice().setText(seller.getSerialDevice());
		else
			this.display.getSerialDevice().setText("");	
	}
	
	private void clearInfo(){
		this.display.getName().setText("");
		this.display.getLastName().setText("");
		this.display.getPassword().setText("");
		this.display.getAddress().setText("");
		this.display.getCity().setText("");
		this.display.getZP().setText("");
		this.display.getTelephone().setText("");
		this.display.getUserName().setText("");
		this.display.getSerialDevice().setText("");	
	}
	
	private void populateSellersList(int startP,int lenghtP){
			search = false;
			final int start = startP;
			final int lenght = lenghtP;
			display.showBusyIndicator();
			new RPCCall<ResultDTO<SellerDTO>>(){
				@Override
				public void onFailure(Throwable caught) {
					display.hideBusyIndicator();
					Window.alert(CloudMobile.constants.eGetSellers());
				}
				@Override
				public void onSuccess(ResultDTO<SellerDTO> result) {
					display.hideBusyIndicator();
					if(result != null){
						display.setRange((start+1), lenght, size);
						pageCursor = result.getCursorString();
						display.getCellList().setRowData(start, result.getList());
					}
					scrollEnable = true;
				}
				@Override
				protected void callService(AsyncCallback<ResultDTO<SellerDTO>> cb) {
					rpcSellerService.getSellers(pageCursor,pageSize,userA.getName(),cb);	
				}
			}.retry(3);
	}
	
	 
	public void doScroll() {
		scrollEnable = false;
		int newRangeLenght;
		int maxScrollTop = display.getMaximumVerticalScrollPosition();
		int oldScrollPos = lastScrollPos;
		lastScrollPos = display.getVerticalScrollPosition();
		int despDesc = oldScrollPos-lastScrollPos;
		if((lastScrollPos == maxScrollTop)&&(despDesc < 2)&&(rangeLength < size))
		{	
			newRangeLenght = rangeLength + pageSize;
			rangeStart = rangeLength;
			if(size < newRangeLenght){
				rangeLength = size;
			}
			else{
				rangeLength = newRangeLenght;
			}
			
			display.getCellList().setVisibleRange(0, rangeLength);
			if(search)
      		  doSearch(rangeStart,rangeLength);
			else
      		  populateSellersList(rangeStart,rangeLength); 	
		}
		else
			scrollEnable = true;
		}
	
	
	@Override
	public void go(HasWidgets container) {
		if(sellerDTO == null){
			updateRowQuantity();				
			clearInfo();
		}
		container.clear();
		container.add(display.asWidget());
		
	}
	public void updateRowQuantity(){
		rpcSellerService.getSellersCount(userA.getName(),new AsyncCallback<Integer>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(CloudMobile.constants.eGetCountSellers());
			}
			@Override
			public void onSuccess(Integer result) {
				size = result.intValue();
				if( (size > 0)){
					if((rangeStart == 0) &&(size < pageSize))
						rangeLength = size;
					display.getCellList().setRowCount(size, true);
					populateSellersList(rangeStart,rangeLength);
				}
				else{
					display.getCellList().setRowCount(0,true);
					display.setRange(rangeStart, 0, size);
				}
			}});		
	}
	
	public void updateSRowQuantity(){
		rpcSellerService.getSResultsCount(searchParam,new AsyncCallback<Integer>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(CloudMobile.constants.eGetCountSellers());
			}
			@Override
			public void onSuccess(Integer result) {
				size = result.intValue();
				if(size > 0){
					if(((rangeStart == 0)&&(size < pageSize))){
						rangeLength = size;
					}
					display.getCellList().setRowCount(size, true);
					doSearch(rangeStart,rangeLength);
				}
				else{
					display.getCellList().setRowCount(0, true);
					display.setRange(rangeStart, 0, size);
				}
								
			}});	
		
	}
	public SellerDTO getSellerSelected(){
		return sellerDTO;
	}
	
}
